/**
 * MIT License
 * 
 * Copyright (c) 2017 CaiDongyu
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.tunnel.client.config;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import com.tunnel.common.tunnel.TunnelDataQueue;
import com.tunnel.common.util.LogUtil;
import com.tunnel.common.util.PropsUtil;
import com.tunnel.common.util.StringUtil;

public class Config {
	public static String TUNNEL_SERVER_IP;
	public static int TUNNEL_SERVER_PORT;

	public static String NAME;
	
	//HTTP
	public static String HOST_ARY;
	public static List<IpAndPort> HOST_LIST = new ArrayList<>();
	//TCP
	public static String TCP_ARY;
	public static List<IpAndPort> TCP_LIST = new ArrayList<>();
	//UDP
	public static String UDP_ARY;
	public static List<IpAndPort> UDP_LIST = new ArrayList<>();
	
	public static void init(String configFileUrl){
		
		Properties props = PropsUtil.loadProps(configFileUrl);
		if(props == null){
			LogUtil.e("配置文件不存在："+configFileUrl);
			System.exit(0);
		}
		TUNNEL_SERVER_IP = PropsUtil.getString(props, "tunnel_server_ip");
		if (StringUtil.isEmpty(TUNNEL_SERVER_IP)) {
			LogUtil.e("服务器[IP]配置错误：tunnel_server_ip=" + TUNNEL_SERVER_IP);
			System.exit(0);
		}

		TUNNEL_SERVER_PORT = PropsUtil.getInt(props, "tunnel_server_port");
		if (TUNNEL_SERVER_PORT <= 0) {
			LogUtil.e("服务器[端口]配置错误：tunnel_server_port=" + TUNNEL_SERVER_PORT);
			System.exit(0);
		}
		
		String tunnel_speed = PropsUtil.getString(props, "tunnel_speed");
		try {
			TunnelDataQueue.setITEM_SIZE(tunnel_speed);
		} catch (Exception e) {
			LogUtil.e("Tunnel管道[速率限制]配置错误："+e.getMessage() );
			System.exit(0);
		}
		
		NAME = PropsUtil.getString(props, "name");
		if (StringUtil.isEmpty(NAME)) {
			LogUtil.e("客户端[名称]配置错误：name=" + NAME);
			System.exit(0);
		}

		HOST_ARY = PropsUtil.getString(props, "host_ary");
		if(StringUtil.isNotEmpty(HOST_ARY)){
			//查看域名和地址的映射
			String[] hostAry = HOST_ARY.trim().split(",");
			
			for(String host:hostAry){
				//检查域名配置
				if(host != null) host=host.trim();
				if(StringUtil.isEmpty(host)){
					LogUtil.e("客户端[域名列表]配置错误：host_ary=" + HOST_ARY);
					System.exit(0);
				}
				
				//检查域名映射配置
				String mapper = PropsUtil.getString(props, "host_"+host);
				if(mapper != null) mapper = mapper.trim();
				if(StringUtil.isEmpty(mapper)){
					LogUtil.e("客户端[域名映射]配置错误：host_"+host+"=" + mapper);
					System.exit(0);
				}
				String[] ipAndPortConfig = mapper.split(":");
				if(ipAndPortConfig.length < 2){
					LogUtil.e("客户端[域名映射]配置错误（提示 ip:端口）host_："+host+"=" + mapper);
					System.exit(0);
				}
				
				addHostIpAndPort(ipAndPortConfig, host, mapper);
			}
		}
		
		
		
		TCP_ARY = PropsUtil.getString(props, "tcp_ary");
		if(StringUtil.isNotEmpty(TCP_ARY)){
			//查看域名和地址的映射
			String[] tcpAry = TCP_ARY.trim().split(",");
			
			for(String port:tcpAry){
				//检查域名配置
				if(port != null) port=port.trim();
				if(StringUtil.isEmpty(port)){
					LogUtil.e("客户端[tcp列表]配置错误：tcp_ary=" + TCP_ARY);
					System.exit(0);
				}
				
				//检查域名映射配置
				String mapper = PropsUtil.getString(props, "tcp_"+port);
				if(mapper != null) mapper = mapper.trim();
				if(StringUtil.isEmpty(mapper)){
					LogUtil.e("客户端[tcp映射]配置错误：tcp_"+port+"=" + mapper);
					System.exit(0);
				}
				String[] ipAndPortConfig = mapper.split(":");
				if(ipAndPortConfig.length < 2){
					LogUtil.e("客户端[tcp映射]配置错误（提示 ip:端口）：tcp_"+port+"=" + mapper);
					System.exit(0);
				}
				
				addTcpIpAndPort(ipAndPortConfig, port, mapper);
			}
		}
		
		

		UDP_ARY = PropsUtil.getString(props, "udp_ary");
		if(StringUtil.isNotEmpty(UDP_ARY)){
			//查看域名和地址的映射
			String[] udpAry = UDP_ARY.trim().split(",");
			
			for(String port:udpAry){
				//检查域名配置
				if(port != null) port=port.trim();
				if(StringUtil.isEmpty(port)){
					LogUtil.e("客户端[udp列表]配置错误：udp_ary=" + UDP_ARY);
					System.exit(0);
				}
				
				//检查域名映射配置
				String mapper = PropsUtil.getString(props, "udp_"+port);
				if(mapper != null) mapper = mapper.trim();
				if(StringUtil.isEmpty(mapper)){
					LogUtil.e("客户端[udp映射]配置错误：udp_"+port+"=" + mapper);
					System.exit(0);
				}
				String[] ipAndPortConfig = mapper.split(":");
				if(ipAndPortConfig.length < 2){
					LogUtil.e("客户端[udp映射]配置错误（提示 ip:端口）：udp_"+port+"=" + mapper);
					System.exit(0);
				}
				
				addUdpIpAndPort(ipAndPortConfig, port, mapper);
			}
		}
	}
	
	private static void addHostIpAndPort(String[] ipAndPortConfig, String host, String mapper){
		try {
			//与应用服务器通讯后，反馈给tunnel-server的数据包传递速度设置，0表示最慢，1表示满速
			IpAndPort ipAndPort = new IpAndPort(ipAndPortConfig[0], Integer.parseInt(ipAndPortConfig[1]));
			HOST_LIST.add(ipAndPort);
		} catch (Exception e) {
			LogUtil.e("客户端[域名映射]配置错误（提示 ip:端口）：host_"+host+"=" + mapper);
			System.exit(0);
		}
	}

	private static void addTcpIpAndPort(String[] ipAndPortConfig, String port, String mapper){
		try {
			//与应用服务器通讯后，反馈给tunnel-server的数据包传递速度设置，0表示最慢，1表示满速
			IpAndPort ipAndPort = new IpAndPort(ipAndPortConfig[0], Integer.parseInt(ipAndPortConfig[1]));
			TCP_LIST.add(ipAndPort);
		} catch (Exception e) {
			LogUtil.e("客户端[tcp映射]配置错误（提示 ip:端口）：tcp_"+port+"=" + mapper);
			System.exit(0);
		}
	}

	private static void addUdpIpAndPort(String[] ipAndPortConfig, String port, String mapper){
		try {
			//与应用服务器通讯后，反馈给tunnel-server的数据包传递速度设置，0表示最慢，1表示满速
			IpAndPort ipAndPort = new IpAndPort(ipAndPortConfig[0], Integer.parseInt(ipAndPortConfig[1]));
			UDP_LIST.add(ipAndPort);
		} catch (Exception e) {
			LogUtil.e("客户端[udp映射]配置错误（提示 ip:端口）：udp_"+port+"=" + mapper);
			System.exit(0);
		}
	}
}
